home *** CD-ROM | disk | FTP | other *** search
/ Aminet 39 / Aminet 39 (2000)(Schatztruhe)[!][Oct 2000].iso / Aminet / game / shoot / Orbit_src.lha / Orbit / source / model.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-04  |  9.4 KB  |  491 lines

  1. /*
  2.     Amiga port by Oliver Gantert
  3.  
  4.     27.04.2000 - fixed some compiler warnings
  5. */
  6. /*
  7.  
  8. ORBIT, a freeware space combat simulator
  9. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  10.  
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License
  13. as published by the Free Software Foundation; either version 2
  14. of the License, or (at your option) any later version.
  15.  
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License
  22. along with this program; if not, write to the Free Software
  23. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  24.  
  25. */
  26.  
  27. #include "orbit.h"
  28.  
  29. /*
  30.  *  Routines to manipulate object models.
  31.  *  Models are stored as "triangle" files in the "models" directory.
  32.  */
  33.  
  34. void InitModels()
  35. /*
  36.  *  Set up models structures
  37.  */
  38. {
  39.   int m;
  40.  
  41.   for (m=0; m<NMODELS; m++)
  42.   {
  43.     model[m].in_use = 0;
  44.     model[m].name[0] = 0;
  45.     model[m].list = (-1);
  46.   }
  47. }
  48.  
  49. void ResetModels() 
  50. /* 
  51.  *  Get rid of all models 
  52.  */ 
  53. {
  54.   int m; 
  55.   
  56.   for (m=0; m<NMODELS; m++) 
  57.   {
  58.     model[m].in_use = 0; 
  59.     model[m].name[0] = 0; 
  60.     if (glIsList (model[m].list)) glDeleteLists (model[m].list, 1); 
  61.     model[m].list = (-1); 
  62.   }
  63. }
  64.  
  65. int FindModel ()
  66. /*
  67.  *  Find an unused model
  68.  */
  69. {
  70.   int m;
  71.  
  72.   for (m=0; m<NMODELS; m++)
  73.   {
  74.     if (!model[m].in_use) return (m);
  75.   }
  76.  
  77.   Log ("FindModel: Out of models!  Increase NMODELS in orbit.h!");
  78.   FinishSound();
  79.   CloseLog();
  80.   exit (0);
  81. }
  82.  
  83. struct tri_struct
  84. {
  85.   int v1, v2, v3;
  86.   int hex;
  87.   int done;
  88.   double norm[3];
  89. }
  90. *tri;
  91.  
  92. struct vert_struct
  93. {
  94.   double v[3];
  95. }
  96. *vert;
  97.  
  98. int ntris;
  99. int nverts;
  100. int verts;
  101. int parity;
  102. int orphans;
  103. int length;
  104. int stripped;
  105. int lasthex;
  106.  
  107. int LoadModel (char *name)
  108. /*
  109.  *  Load a triangle file, make display list, return list ID
  110.  */
  111. {
  112.   char fn[32];
  113.   FILE *fd;
  114.   int hex, m, len;
  115.   double v1[3], v2[3], v3[3], n1[3], n2[3], norm[3]; 
  116.   
  117.   /* Hand off if it's an AC3D model */ 
  118.   len = strlen (name); 
  119.   if ( (len > 3) && (!strcasecmp (&name[len-2], "ac")) ) 
  120.   {
  121.     return (LoadAC3D (name)); 
  122.   }
  123.  
  124.   /* See if it's already loaded */
  125.   for (m=0; m<NMODELS; m++)
  126.   {
  127.     if (!strcmp (model[m].name, name)) return (m);
  128.   }
  129.  
  130.   Log ("LoadModel: Loading model %s", name);
  131.  
  132.   /* Allocate space for triangles and vertices */
  133.   if (NULL == (tri = (struct tri_struct *)
  134.   malloc (4096 * sizeof (struct tri_struct))))
  135.   {
  136.     OutOfMemory();
  137.   }
  138.   if (NULL == (vert = (struct vert_struct *)
  139.   malloc (4096 * sizeof (struct vert_struct))))
  140.   {
  141.     OutOfMemory();
  142.   }
  143.  
  144.   /* Find an unused model index */
  145.   m = FindModel();
  146.   strcpy (model[m].name, name);
  147.   model[m].in_use = 1;
  148.  
  149.   /* Get a list id */
  150.   model[m].list = glGenLists (1);
  151.   glNewList (model[m].list, GL_COMPILE);
  152.  
  153.   /* Construct file name */
  154.   sprintf (fn, "models/%s", name);
  155.  
  156.   /* Open it */
  157.   if (NULL == (fd = fopen (fn, "r")))
  158.   {
  159.     Log ("LoadModel: Can't open %s, giving up!", fn);
  160.     return (-1);
  161.   }
  162.  
  163.   ntris = 0;
  164.   verts = 0;
  165.   nverts = 0;
  166.   orphans = 0;
  167.   lasthex = -1;
  168.  
  169.   /* Read them triangles */
  170.   while (10 == fscanf (fd, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %i",
  171.   &v1[0], &v1[1], &v1[2], &v2[0], &v2[1], &v2[2],
  172.   &v3[0], &v3[1], &v3[2], &hex))
  173.   {
  174.     Vdiv (v1, v1, 100.0);
  175.     Vdiv (v2, v2, 100.0);
  176.     Vdiv (v3, v3, 100.0);
  177.  
  178.     /* Compute normal */
  179.     Vsub (n1, v3, v2);
  180.     Normalize (n1);
  181.     Vsub (n2, v1, v2);
  182.     Normalize (n2);
  183.     Crossp (norm, n1, n2);
  184.     Normalize (norm);
  185.  
  186.     /* Make triangle structure */
  187.     tri[ntris].v1 = AddVertex (v1);
  188.     tri[ntris].v2 = AddVertex (v2);
  189.     tri[ntris].v3 = AddVertex (v3);
  190.  
  191.     Vset (tri[ntris].norm, norm);
  192.     tri[ntris].done = 0;
  193.     tri[ntris].hex = hex;
  194.  
  195.     ntris++;
  196.   }
  197.   fclose (fd); 
  198.   
  199.   /* Make models about the same size in network games */ 
  200.   if (am_client || am_server) ScaleModel (m); 
  201.   
  202.   /* Make into triangle strips */
  203.   MakeStrips();
  204.  
  205.   glEndList();
  206.  
  207.   /* Construct bounding box */
  208.   ModelBounds (m);
  209.  
  210.   free (tri);
  211.   free (vert);
  212.  
  213.   return (m);
  214. }
  215.  
  216. void MakeStrips()
  217. /*
  218.  *  Since the triangle model consists of sparse triangles and we
  219.  *  want to use triangle strips for performance, this routine slices
  220.  *  and dices the triangles to make them into strips where it can.
  221.  *  The result is not optimal, but it typically cuts the number of
  222.  *  transformed vertices in half and sometimes does much better.
  223.  */
  224. {
  225.   int t, a;
  226.  
  227.   Log ("MakeStrips: Total triangles: %d", ntris);
  228.   Log ("MakeStrips: Total vertices: %d", nverts);
  229.  
  230.   /* While there are more */
  231.   while ((-1) != (t = FindTriangle()))
  232.   {
  233.     verts += 3;
  234.     parity = 0;
  235.     stripped = 0;
  236.     length = 1;
  237.  
  238.     glBegin (GL_TRIANGLE_STRIP);
  239.  
  240.     /* While there is an adjacent triangle */
  241.     while ((-1) != (a = FindAdjacent(t)))
  242.     {
  243.       if (length == 1)
  244.       {
  245.         Normal (t);
  246.         Vertex (tri[t].v1);
  247.         Vertex (tri[t].v2);
  248.         Vertex (tri[t].v3);
  249.       }
  250.       Normal (a);
  251.       Vertex (tri[a].v3);
  252.       stripped++;
  253.       tri[t].done = 1;
  254.       tri[a].done = 1;
  255.       t = a;
  256.       verts++;
  257.       parity = !parity;
  258.       length++;
  259.     }
  260.  
  261.     if (!stripped)
  262.     {
  263.       flop (t);
  264.       while ((-1) != (a = FindAdjacent(t)))
  265.       {
  266.         if (length == 1)
  267.         {
  268.           Normal (t);
  269.           Vertex (tri[t].v1);
  270.           Vertex (tri[t].v2);
  271.           Vertex (tri[t].v3);
  272.         }
  273.         Normal (a);
  274.         Vertex (tri[a].v3);
  275.         stripped++;
  276.         tri[t].done = 1;
  277.         tri[a].done = 1;
  278.         t = a;
  279.         verts++;
  280.         parity = !parity;
  281.         length++;
  282.       }
  283.     }
  284.  
  285.     if (!stripped)
  286.     {
  287.       flop (t);
  288.       while ((-1) != (a = FindAdjacent(t)))
  289.       {
  290.         if (length == 1)
  291.         {
  292.           Normal (t);
  293.           Vertex (tri[t].v1);
  294.           Vertex (tri[t].v2);
  295.           Vertex (tri[t].v3);
  296.         }
  297.         Normal (a);
  298.         Vertex (tri[a].v3);
  299.         stripped++;
  300.         tri[t].done = 1;
  301.         tri[a].done = 1;
  302.         t = a;
  303.         verts++;
  304.         parity = !parity;
  305.         length++;
  306.       }
  307.     }
  308.  
  309.     if (!stripped)
  310.     {
  311.       Normal (t);
  312.       Vertex (tri[t].v1);
  313.       Vertex (tri[t].v2);
  314.       Vertex (tri[t].v3);
  315.  
  316.       /* We get here if triangle t couldn't be put
  317.       in a triangle strip */
  318.       tri[t].done = 1;
  319.       orphans++;
  320.     }
  321.  
  322.     glEnd();
  323.   }
  324.  
  325.   Log ("MakeStrips: Rendered vertices: %d (would have been %d, bare minimum %d)",
  326.   verts, 3*ntris, nverts);
  327.   Log ("MakeStrips: Orphaned triangles: %d", orphans);
  328. }
  329.  
  330. int FindTriangle()
  331. {
  332.   int t;
  333.  
  334.   for (t = 0; t<ntris; t++)
  335.   {
  336.     if (!tri[t].done) return (t);
  337.   }
  338.   return (-1);
  339. }
  340.  
  341. int FindAdjacent (int t)
  342. {
  343.   int a, i;
  344.  
  345.   for (a=0; a<ntris; a++)
  346.   {
  347.     if ( (a != t) && (!tri[a].done) )
  348.     {
  349.       if (parity == 0)
  350.       {
  351.         for (i=0; i<3; i++)
  352.         {
  353.           if ( (tri[t].v2 == tri[a].v2) &&
  354.           (tri[t].v3 == tri[a].v1) &&
  355.           (tri[t].hex == tri[a].hex) )
  356.           return (a);
  357.           flop (a);
  358.         }
  359.       }
  360.       else
  361.       {
  362.         for (i=0; i<3; i++)
  363.         {
  364.           if ( (tri[t].v3 == tri[a].v2) &&
  365.           (tri[t].v1 == tri[a].v1) &&
  366.           (tri[t].hex == tri[a].hex) )
  367.           return (a);
  368.           flop (a);
  369.         }
  370.       }
  371.     }
  372.   }
  373.   return (-1);
  374. }
  375.  
  376. void flop (int t)
  377. {
  378.   int v;
  379.  
  380.   v = tri[t].v1;
  381.   tri[t].v1 = tri[t].v2;
  382.   tri[t].v2 = tri[t].v3;
  383.   tri[t].v3 = v;
  384. }
  385.  
  386. int Veq (int v1, int v2)
  387. {
  388.   return (v1 == v2);
  389. }
  390.  
  391. int AddVertex (double *v)
  392. {
  393.   int i;
  394.  
  395.   for (i=0; i<nverts; i++)
  396.   {
  397.     if ( (v[0] == vert[i].v[0]) &&
  398.     (v[1] == vert[i].v[1]) &&
  399.     (v[2] == vert[i].v[2]) ) return (i);
  400.   }
  401.  
  402.   Vset (vert[nverts].v, v);
  403.   nverts++;
  404.  
  405.   return (nverts-1);
  406. }
  407.  
  408. void Vertex (int v)
  409. {
  410.   glVertex3d (vert[v].v[0], vert[v].v[1], vert[v].v[2]);
  411. }
  412.  
  413. void Normal (int t)
  414. {
  415.   float color[3];
  416.  
  417.   if (tri[t].hex != lasthex)
  418.   {
  419.     lasthex = tri[t].hex;
  420.     color[0] = ((float) (tri[t].hex / 65536)) / 256.0;
  421.     color[1] = ((float) ((tri[t].hex % 65536) / 256)) / 256.0;
  422.     color[2] = ((float) (tri[t].hex % 256)) / 256.0;
  423.     glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  424.     glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, color);
  425.   }
  426.   glNormal3dv (tri[t].norm);
  427. }
  428.  
  429. void ModelBounds (int m)
  430. /*
  431.  *  Construct bounding box of model m
  432.  */
  433. {
  434.   int i, v;
  435.   double mm;
  436.  
  437.   for (i=0; i<3; i++)
  438.   {
  439.     model[m].lobound[i] = model[m].hibound[i] = vert[0].v[i];
  440.   }
  441.  
  442.   for (v=1; v<nverts; v++)
  443.   {
  444.     for (i=0; i<3; i++)
  445.     {
  446.       if (vert[v].v[i] < model[m].lobound[i])
  447.       model[m].lobound[i] = vert[v].v[i];
  448.  
  449.       if (vert[v].v[i] > model[m].hibound[i])
  450.       model[m].hibound[i] = vert[v].v[i];
  451.     }
  452.   }
  453.  
  454.   Log ("ModelBounds: Lo bounds: %lf %lf %lf", model[m].lobound[0],
  455.   model[m].lobound[1], model[m].lobound[2]);
  456.   Log ("ModelBounds: Hi bounds: %lf %lf %lf", model[m].hibound[0],
  457.   model[m].hibound[1], model[m].hibound[2]);
  458.  
  459.   /* Figure radius of bounding sphere */
  460.   model[m].radius = Mag (model[m].lobound);
  461.   if ((mm = Mag (model[m].hibound)) > model[m].radius)
  462.   model[m].radius = mm;
  463.   model[m].radius2 = model[m].radius * model[m].radius;
  464. }
  465.  
  466. void ScaleModel (int m)
  467. /* 
  468.  *  Make models a uniform size 
  469.  */ 
  470. {
  471.   double ratio; 
  472.   int v, i; 
  473.   
  474.   /* Compute existing model bounds */ 
  475.   ModelBounds (m); 
  476.   
  477.   if (model[m].radius == 0.0) return; 
  478.   
  479.   /* Want everything to have a radius of, say, 0.030 */ 
  480.   ratio = model[m].radius / 0.030; 
  481.   
  482.   /* Scale all the vertices */ 
  483.   for (v=0; v<nverts; v++) 
  484.   {
  485.     for (i=0; i<3; i++) 
  486.     {
  487.       vert[v].v[i] /= ratio; 
  488.     }
  489.   }
  490. }
  491.